package org.libsdl.app;

import java.nio.ByteBuffer;
import java.util.Date;

import com.example.cyclops.R;

import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.app.Activity;
import android.media.MediaCodec;
import android.media.MediaFormat;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.KeyEvent;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.view.View.OnClickListener;
import android.widget.TextView;
import android.widget.Toast;

public class MythHardwareDecoder extends Activity implements
		SurfaceHolder.Callback, OnClickListener {

	private static final String TAG = "MythHardwareDecoder";
	private SurfaceView surfaceView;
	private SurfaceHolder surfaceHolder;
	private MediaCodec mMediaDecoder;
	private Surface mSurface;
	private int mSurfaceWidth;
	private int mSurfaceHeight;
	private int mFrameIndex = 0;
	private String ip;
	private String cameraid;
	private String cameratext;
	private DecoderTask mainTask;
	private static final int FRAME_RATE = 25;
	private boolean firstrun = true;
	private boolean isExit = false;
	
	Handler mHandler = new Handler() {
		@Override
		public void handleMessage(Message msg) {
			super.handleMessage(msg);
			isExit = false;
		}

	};
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);

        //去除title
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        //去掉Activity上面的状态栏
        this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);//去掉信息栏
        WindowManager.LayoutParams params = getWindow().getAttributes();
        params.systemUiVisibility = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
        getWindow().setAttributes(params);
		getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
		setContentView(R.layout.hardwared);

		mMediaDecoder = null;
		mSurface = null;
		mFrameIndex = 0;
		firstrun = true;
		if (!setupView()) {
			Log.e(TAG, "failed to setupView");
			return;
		}

		Bundle bundle = this.getIntent().getExtras();
		if (bundle != null) {
			ip = bundle.getString("ip");
			cameraid = bundle.getString("cameraid");
			cameratext = bundle.getString("cameratext");
		}
		Log.e("SDL", "ip = " + ip);
		Log.e("SDL", "cameraid = " + cameraid);
	}
	
	private Handler handler = new Handler() {  
        @Override  
        public void handleMessage(Message msg) {  
        	Bundle b = msg.getData(); 
            String str = b.getString("String"); 
            SetString(str);
        }  
    };
	private long presentationTimeUs = ~0; 
    
	private void SetString(String text){
		TextView texttag = (TextView) findViewById(R.id.texttag);
		texttag.setText(text);
	}
	
	class DecoderTask extends Thread {
		int m_cameraid;
		String _uri;
		String _tag;
		boolean hasDataCome;
		boolean isrunning;
		byte[] recvBuf;
		int times;
		
		
		private String GenrateString(){
			String tmp = "loading";
			int pertime = times / 300;
			for(int i = 0;i < pertime % 5;i++){
				tmp += ".";
			}
			times++;
			return tmp;
		}
		public DecoderTask(String ip, int port, int cameraid, String tag) {
			//InitalRtmpLink(ip);
			_uri = ip;
			hasDataCome = false;
			m_cameraid = cameraid;
			isrunning = true;
			_tag = tag;
			recvBuf = new byte[1024 * 1024];
			times = 0;
		}

		public void Stop() {
			isrunning = false;
		}

		@Override
		public void run() {
			InitalP2PLink(m_cameraid,ip);
			if (mMediaDecoder == null) {
				if (!setupDecoder(mSurface, "video/avc", mSurfaceWidth,
						mSurfaceHeight)) {
					Log.e(TAG, "failed to setupDecoder");
					return;
				}
			}
			int status = 0;
			long time_base = new Date().getTime();
			while (isrunning == true) {
				int len = GetRtmpBuf(recvBuf, recvBuf.length);
				if (len > 0) {
					if(!this.hasDataCome){
						this.hasDataCome = true;
						Message msg = new Message();  
						Bundle b = new Bundle();// 存放数据 
			            b.putString("String", _tag); 
				        msg.setData(b);
				        handler.sendMessage(msg);  
					}
					offerDecoder(recvBuf, len);
				}else{
					try {
						Thread.sleep(1);
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					if(!this.hasDataCome){
						if(status == 0){
							long time_now = new Date().getTime();
							if(time_now - time_base > 5000){
								Log.d("change mode", "change to rtmp mode");
								CloseRtmpLink();
								InitalRtmpLink(_uri);
								status = 1;
							}
						}
						Message msg = new Message();  
						Bundle b = new Bundle();// 存放数据 
			            b.putString("String",GenrateString()); 
				        msg.setData(b);
				        handler.sendMessage(msg);  
						//SetString(GnerateString());
					}
				}
			}
			CloseRtmpLink();
		}
	}

	@SuppressLint("NewApi") private boolean setupDecoder(Surface surface, String mime, int width,
			int height) {
		Log.d(TAG, "setupDecoder surface:" + surface + " mime:" + mime + " w:"
				+ width + " h:" + height);

		MediaFormat mediaFormat = MediaFormat.createVideoFormat(mime, width,
				height);
		mMediaDecoder = MediaCodec.createDecoderByType(mime);
		if (mMediaDecoder == null) {
			Log.e("DecodeActivity", "createDecoderByType fail!");
			return false;
		}
		
		mMediaDecoder.configure(mediaFormat, surface, null, 0);
		mMediaDecoder.start();

		return true;
	}
	
	private void offerDecoder(byte[] input, int length) {
		try {
			ByteBuffer[] inputBuffers = mMediaDecoder.getInputBuffers();
			int inputBufferIndex = mMediaDecoder.dequeueInputBuffer(-1);
			if (inputBufferIndex >= 0) {
				ByteBuffer inputBuffer = inputBuffers[inputBufferIndex];
				if(presentationTimeUs == ~0){
					presentationTimeUs = new Date().getTime();
				}
				long pts = new Date().getTime() - presentationTimeUs ;
				//long timestamp = mFrameIndex++ * 1000000 / FRAME_RATE;
				Log.d(TAG, "offerDecoder timestamp: " + pts
						+ " inputSize: " + length + " bytes");
				inputBuffer.clear();
				inputBuffer.put(input, 0, length);
				mMediaDecoder.queueInputBuffer(inputBufferIndex, 0, length,
						pts, 0);
			}

			MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();
			int outputBufferIndex = mMediaDecoder.dequeueOutputBuffer(bufferInfo, 0);
			while (outputBufferIndex >= 0) {
				// If a valid surface was specified when configuring the codec,
				// passing true renders this output buffer to the surface.
				mMediaDecoder.releaseOutputBuffer(outputBufferIndex, true);
				outputBufferIndex = mMediaDecoder.dequeueOutputBuffer(bufferInfo, 0);
			}
		} catch (IllegalStateException e) {  
			this.mMediaDecoder.stop();
			this.mMediaDecoder = null;
			this.setupDecoder(mSurface, "video/avc", mSurfaceWidth,mSurfaceHeight);
			Log.d(TAG, "restart media decoder");
			e.printStackTrace();
		} catch (Throwable t) {
			t.printStackTrace();
		}
	}

	@Override
	public void surfaceChanged(SurfaceHolder holder, int format, int width,
			int height) {
		// TODO Auto-generated method stub

		Log.i(TAG, "surfaceChanged w:" + width + " h:" + height);
		mSurface = surfaceHolder.getSurface();

		mSurfaceWidth = width;
		mSurfaceHeight = height;
		if (firstrun) {
			firstrun = !firstrun;
			mainTask = new DecoderTask(ip, 1935, Integer.parseInt(cameraid),cameratext);
			mainTask.start();
		}
	}

	/**
	 * 
	 */
	private boolean setupView() {
		Log.d(TAG, "fall in setupView");

		if (null != surfaceHolder) {
			surfaceHolder.removeCallback(this);
			surfaceView = null;
		}
		if (null != surfaceView) {
			surfaceView = null;
		}

		surfaceView = (SurfaceView) findViewById(R.id.surfaceView);
		surfaceHolder = surfaceView.getHolder();
		surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
		surfaceHolder.addCallback(this);
		return true;
	}

	@Override
	public void surfaceCreated(SurfaceHolder arg0) {
		// TODO Auto-generated method stub
		this.mSurface = arg0.getSurface();

	}

	@Override
	public void surfaceDestroyed(SurfaceHolder arg0) {
		// TODO Auto-generated method stub
		mainTask.Stop();
		mMediaDecoder.stop();
	}

    // Load the .so
    static {
        System.loadLibrary("SDL2");
        System.loadLibrary("main");
    }

    public static native int InitalP2PLink(int userid,String uri);
    public static native int InitalRtmpLink(String uri);
    public static native int GetRtmpBuf(byte[] data,int len);
    public static native int CloseRtmpLink();
    
	@Override
	public void onClick(View arg0) {
		// TODO Auto-generated method stub

	}

}
